package pikasial.utils;

import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.util.Collection;

import javax.imageio.ImageIO;

import pikasial.fs.Dossier;
import pikasial.images.AlbumPhotos;
import pikasial.images.ImageContainer;
import pikasial.images.ListeAlbums;
import pikasial.images.PikImage;

public class GestionnaireCacheVignettes {

    public static final long MAX_MEM_USAGE_ALLOWED = 96000000;
    public static final long DEF_MEM_CHECK_TIME = 60000;
    public static final long DEF_CACHE_SIZE = 128000000;
    public static final long MAX_CACHE_SIZE = 512000000;
    public static final long MIN_CACHE_SIZE = 0;
    protected long cacheSize;
    protected File thumbnailFolder;
    private static GestionnaireCacheVignettes instance = new GestionnaireCacheVignettes();

    private GestionnaireCacheVignettes() {
        thumbnailFolder = new File(pikasial.Configuration.DEF_THUMBS_FOLDER);
        try {
            cacheSize = Long.parseLong(pikasial.Configuration.getInstance().getProperty("cache.size"));
        } catch (NumberFormatException nfe) {
            cacheSize = DEF_CACHE_SIZE;
        }
        launchMemoryChecker();
    }

    public static GestionnaireCacheVignettes getInstance() {
        return instance;
    }

    public static boolean checkAvailableMemory() {
        MemoryMXBean mxb = ManagementFactory.getMemoryMXBean();
        java.lang.management.MemoryUsage mu = mxb.getHeapMemoryUsage();
        return (mu.getUsed() <= MAX_MEM_USAGE_ALLOWED);
    }

    private void launchMemoryChecker() {
    	new Thread(new Runnable() {
    		public void run() {
    			while (true) {
    				try {
    					Thread.sleep(DEF_MEM_CHECK_TIME);
    					System.out.println("Verification de la mémoire disponible...");
    					if (!checkAvailableMemory()) {
    						System.out.println("Mémoire pleine, vidage des vignettes !");
    						for (AlbumPhotos ap : ListeAlbums.getInstance().getAllAlbums()) {
    							if (ap != ListeAlbums.getInstance().getAlbumAffiche())
    								viderVignettes(ap);
    						}
    						for (Dossier d : ListeAlbums.getInstance().getAllDossiers()) {
    							if (d != ListeAlbums.getInstance().getAlbumAffiche())
    								viderVignettes(d);
    						}
    						System.gc();
    					} else System.out.println("OK");
    				} catch (InterruptedException ie) {}
    			}
    		}
    	}).start();
    }

    public void saveThumbnailsToDisk(ImageContainer im) throws IOException {
    	if (!thumbnailFolder.exists())
    		thumbnailFolder.mkdir();
        File f;
        System.out.println("Sauvegarde vignettes sur disque.");
        if (im != null) {
            Collection<PikImage> collec = im.getAllImages();
            if (availablePlaceInCache() <= 0) {
                throw new IOException("La taille des vignettes à sauvegarder est supérieure" + " à la taille disponible dans le cache. \nVous pouvez régler la taille" + " du cache et le vider, dans vos préférences.\n");
            }
            for (PikImage pik : collec) {
                String ext = ExtensionsImages.getExtensionFichier(pik.getJavaFile()).toLowerCase();
//                String exts[] = ImageIO.getWriterFormatNames();
                String exts[] = ImageIO.getWriterFileSuffixes();
                boolean trouve = false;
                for (int i = 0; i < exts.length && !trouve; i++) {
                    if (exts[i].equals(ext)) {
                        trouve = true;
                    }
                }
                if (!trouve) {
                    throw new IOException("Impossible d'enregistrer " + pik.getName() +
                        " sur le disque! Format d'image non pris en charge.");
                }
                f = new File(thumbnailFolder, Math.abs(pik.hashCode()) + "." + ext.toLowerCase());
                if (!f.exists()) {
                    ImageIO.write(pik.getVignette(), ext, f);
                }
            }
        }
    }

    public void setFolder(String newFolder) {
    	thumbnailFolder = new File(newFolder);
    }

    public void viderVignettes(ImageContainer ic) {
        for (PikImage pik : ic.getAllImages()) {
            pik.resetVignette();
        }
    }

//	public long getSizeOfThumbnails(Collection<PikImage> im) {
//		long size = 0;
//		for (PikImage pik : im) {
//			size += pik.getJavaFile().length();
//		}
//		return size;
//	}
    public void setCacheSize(long size) {
        if (size <= MAX_CACHE_SIZE && size >= MIN_CACHE_SIZE) {
            cacheSize = size;
        }
    }

    public long getCacheSize() {
        return cacheSize;
    }

    public void viderCache() throws SecurityException {
        new Thread(new Runnable() {
            public void run() {
                File[] fils = thumbnailFolder.listFiles();
                for (File f : fils) {
                    f.delete();
                }
            }
        }).start();
    }

    public long availablePlaceInCache() throws SecurityException {
        File[] fils = thumbnailFolder.listFiles();
        long usedSpace = 0;
        for (File f : fils) {
            usedSpace += f.length();
        }
        return cacheSize - usedSpace;
    }
}
